#ifndef __READ_SET_H__
#define __READ_SET_H__

#include <stdio.h>
#include <iostream>
#include <fstream>
#include <mian_util.h>
#include "QuerySet.h"
#include "alignerOutput.h"
#include "Settings.h"

using namespace std;

class ReadSet {
public:
	ReadSet() : _readLength(0) {};
	ReadSet(string fileName, const int readLength);
	~ReadSet();
	/**
 	* @return the real number of reads fetched, may be smaller than numReadFetch
 	* @param base
 	* @param qscore
 	* @param numReadFetch the number of reads to fetch
 	* */
	int fetch(char* base, char* qscore, const int numReadFetch);

	/*utilities*/
	static void encode(QuerySet &querySet, const char* read, 
			const int numRead, const int readLength, bool isTwoStrand = false);
	inline static void encodeSingle(unsigned int *encodedQuery, const char *read, const int readLength);
	inline static int numEncodedWord(const int numBase);
	inline static int encodeBase(const char c);
	
private:
	const int _readLength;
	ifstream _ifs;

	bool isGoodRead(string read);
};






/////////////////////////////////////////////////////////
//the inline functions


int ReadSet::encodeBase(const char b) {
	switch(b) {
		case 'A':
			return 0;
		case 'C':
			return 1;
		case 'G':
			return 2;
		case 'T':
			return 3;
		default:
			cout << "Error: The unknown base: " << b << endl;
			exit(-1);
	}
}

int ReadSet::numEncodedWord(const int numBase) {
	return ceil(numBase/(double)CHAR_PER_WORD);
}

void ReadSet::encodeSingle(unsigned int *encodedQuery, const char *read, const int readLength) {
	const int numWord = numEncodedWord(readLength);	
	int pos = 0;

	for(int wordId = 0; wordId < numWord; wordId ++) {
		for(int k = 0; (k < CHAR_PER_WORD) && (pos < readLength); k++) {
			encodedQuery[wordId] <<= 2;
			encodedQuery[wordId] |= encodeBase(read[pos]);
			++pos;
		}
	}
	//shift the last word to the left-side
	encodedQuery[numWord - 1] <<= (32 - 2*(readLength%CHAR_PER_WORD));
}

#endif /*__READ_SET_H__*/
